const fp = require("lodash/fp");
const fs = require("fs");

class IO {
  static of(value) {
    return new IO(function () {
      return value;
    });
  }

  constructor(fn) {
    this._value = fn;
  }

  map(fn) {
    return new IO(fp.flowRight(fn, this._value));
  }

  join() {
    return this._value();
  }

  flatMap(fn) {
    // 同时调用map和join
    return this.map(fn).join();
  }
}

const readFile = (filename) => {
  return new IO(() => {
    return fs.readFileSync(filename, "utf-8");
  });
};

const print = (str) => {
  return new IO(() => {
    console.log(str);
    return str;
  });
};

// 当我们合并一个函数，并且返回一个函子时，当我们合并一个函数，返回一个值，这时候使用map方法
let r = readFile("../package.json").map(fp.toUpper).flatMap(print).join();
console.log(r);
